package server

import (
	"database/sql"
	"gitee.com/zhendliu/sorm/dialect"
	"gitee.com/zhendliu/sorm/driver/db_dm"
	"gitee.com/zhendliu/sorm/driver/db_gbase"
	"gitee.com/zhendliu/sorm/driver/db_kingbase_v8r6"
	"gitee.com/zhendliu/sorm/driver/db_mysql"
	"gitee.com/zhendliu/sorm/driver/db_opengauss"
	"gitee.com/zhendliu/sorm/driver/db_oracle"
	"gitee.com/zhendliu/sorm/driver/db_postgresql"
	"gitee.com/zhendliu/sorm/driver/db_shentong"
	"gitee.com/zhendliu/sorm/driver/db_sqlite3"
	"gitee.com/zhendliu/sorm/driver/db_yxres"

	"github.com/pkg/errors"
)

type DB struct {
	Db  *sql.DB
	Dia dialect.Dialect
}

// 数据库配置
type Config struct {
	Type            string `json:"type,omitempty"`     // 数据库类型
	Host            string `json:"host,omitempty"`     // 数据库地址
	Port            int    `json:"port,omitempty"`     // 数据库端口
	Database        string `json:"database,omitempty"` // 数据库名 //目前用这个
	DbName          string `json:"dbName,omitempty"`   // 数据库名
	Username        string `json:"username,omitempty"`
	Password        string `json:"password,omitempty"`
	OdbcDsn         string `json:"odbcDsn,omitempty"`
	OdbcDialectName string `json:"odbcDialectName,omitempty"`

	Schema string `json:"schema,omitempty"`
	//CaseSensitive bool   `json:"caseSensitive,omitempty"` //  大小写敏感
	Sid          string `json:"sid,omitempty"`
	MaxIdleConn  int    `json:"maxIdleConn,omitempty"`
	MaxOpenConn  int    `json:"maxOpenConn,omitempty"`
	DatabasePath string `json:"databasePath,omitempty"`
}

// 通过config 初始化一个server.DB
func NewDBWithConfig(config *Config) (sdb *DB, err error) {
	var db *sql.DB
	switch config.Type {
	case "mysql":
		//user string, password string, host string, port int, database string
		db, err = db_mysql.Open(db_mysql.GetDSN(config.Username, config.Password, config.Host, config.Port, config.Database))
		if err != nil {
			panic(err)
		}

	case "kingbase":
		//user string, password string, host string, port int, database string
		db, err = db_kingbase_v8r6.Open(db_kingbase_v8r6.GetDSN(config.Username, config.Password, config.Host, config.Port, config.Database))
		if err != nil {
			panic(err)
		}
	case "dm":
		//user string, password string, host string, port int
		db, err = db_dm.Open(db_dm.GetDSN(config.Username, config.Password, config.Host, config.Port))
		if err != nil {
			panic(err)
		}

	case "shentong":
		//user string, password string, host string, port int, database string
		db, err = db_shentong.Open(db_shentong.GetDSN(config.Username, config.Password, config.Host, config.Port, config.Database))
		if err != nil {
			panic(err)
		}
		// 优炫
	case "yxres":
		db, err = db_yxres.Open(db_yxres.GetDSN(config.Username, config.Password, config.Host, config.Port, config.Database))
		if err != nil {
			panic(err)
		}
	case "opengauss":
		db, err = db_opengauss.Open(db_opengauss.GetDSN(config.Username, config.Password, config.Host, config.Port, config.Database))
		if err != nil {
			panic(err)
		}
	case "oracle":
		db, err = db_oracle.Open(db_oracle.GetDSN(config.Username, config.Password, config.Host, config.Port, config.Database))
		if err != nil {
			panic(err)
		}
	case "postgre", "db_postgresql":
		db, err = db_postgresql.Open(db_postgresql.GetDSN(config.Username, config.Password, config.Host, config.Port, config.Database))
	case "sqlite3", "sqllite":
		db, err = db_sqlite3.Open(db_sqlite3.GetDSN(config.OdbcDsn))
	case "gbase":
		db, err = db_gbase.Open(config.OdbcDsn)

	default:
		panic("unsupport database type")
	}
	if config.MaxIdleConn == 0 {
		config.MaxIdleConn = 1
	}
	if config.MaxOpenConn == 0 {
		config.MaxOpenConn = 10
	}
	err = db.Ping()
	if err != nil {
		return nil, errors.Wrap(err, "failed to ping database")
	}
	db.SetMaxIdleConns(config.MaxIdleConn)
	db.SetMaxOpenConns(config.MaxOpenConn)
	dia, _ := dialect.NewDialect(config.Type)
	sdb = &DB{Db: db, Dia: dia}
	return sdb, nil
}
